1 package org.apache.lucene.util;
2
3 import org.apache.lucene.util.ByteBlockPool.Allocator;
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 public final class RecyclingByteBlockAllocator extends ByteBlockPool.Allocator {
32 private byte[][] freeByteBlocks;
33 private final int maxBufferedBlocks;
34 private int freeBlocks = 0;
35 private final Counter bytesUsed;
36 public static final int DEFAULT_BUFFERED_BLOCKS = 64;
37
38
39
40
41
42
43
44
45
46
47
48 public RecyclingByteBlockAllocator(int blockSize, int maxBufferedBlocks,
49 Counter bytesUsed) {
50 super(blockSize);
51 freeByteBlocks = new byte[maxBufferedBlocks][];
52 this.maxBufferedBlocks = maxBufferedBlocks;
53 this.bytesUsed = bytesUsed;
54 }
55
56
57
58
59
60
61
62
63
64 public RecyclingByteBlockAllocator(int blockSize, int maxBufferedBlocks) {
65 this(blockSize, maxBufferedBlocks, Counter.newCounter(false));
66 }
67
68
69
70
71
72
73
74 public RecyclingByteBlockAllocator() {
75 this(ByteBlockPool.BYTE_BLOCK_SIZE, 64, Counter.newCounter(false));
76 }
77
78 @Override
79 public byte[] getByteBlock() {
80 if (freeBlocks == 0) {
81 bytesUsed.addAndGet(blockSize);
82 return new byte[blockSize];
83 }
84 final byte[] b = freeByteBlocks[--freeBlocks];
85 freeByteBlocks[freeBlocks] = null;
86 return b;
87 }
88
89 @Override
90 public void recycleByteBlocks(byte[][] blocks, int start, int end) {
91 final int numBlocks = Math.min(maxBufferedBlocks - freeBlocks, end - start);
92 final int size = freeBlocks + numBlocks;
93 if (size >= freeByteBlocks.length) {
94 final byte[][] newBlocks = new byte[ArrayUtil.oversize(size,
95 RamUsageEstimator.NUM_BYTES_OBJECT_REF)][];
96 System.arraycopy(freeByteBlocks, 0, newBlocks, 0, freeBlocks);
97 freeByteBlocks = newBlocks;
98 }
99 final int stop = start + numBlocks;
100 for (int i = start; i < stop; i++) {
101 freeByteBlocks[freeBlocks++] = blocks[i];
102 blocks[i] = null;
103 }
104 for (int i = stop; i < end; i++) {
105 blocks[i] = null;
106 }
107 bytesUsed.addAndGet(-(end - stop) * blockSize);
108 assert bytesUsed.get() >= 0;
109 }
110
111
112
113
114 public int numBufferedBlocks() {
115 return freeBlocks;
116 }
117
118
119
120
121 public long bytesUsed() {
122 return bytesUsed.get();
123 }
124
125
126
127
128 public int maxBufferedBlocks() {
129 return maxBufferedBlocks;
130 }
131
132
133
134
135
136
137
138
139 public int freeBlocks(int num) {
140 assert num >= 0 : "free blocks must be >= 0 but was: "+ num;
141 final int stop;
142 final int count;
143 if (num > freeBlocks) {
144 stop = 0;
145 count = freeBlocks;
146 } else {
147 stop = freeBlocks - num;
148 count = num;
149 }
150 while (freeBlocks > stop) {
151 freeByteBlocks[--freeBlocks] = null;
152 }
153 bytesUsed.addAndGet(-count*blockSize);
154 assert bytesUsed.get() >= 0;
155 return count;
156 }
157 }